from List import List
"""
模块AList（AList.py)中定义了以List抽象类型为基础的数据结构AList，该数据结构是线性表，存储表示采用的顺序结构，所有的行为都源自List中的定义。

Authors:
    原盛（homework.xjtu@outlook.com）
Version: 1.0.0
Date: 2025-09-08

"""

class AList(List):
    """
    以顺序结构存储方式实现的线性表数据结构，用于对数据的线性管理，支持插入、删除、定位、查找等操作。

    Attributes:
        _listArray([]):线性表的存储容器，是Python语言内置的数组类型（也被称为list）
        _msize(int):记录了该线性表数据结构能够储存元素个数的最大容量
        _numInList(int):记录了该线性表中的实际元素个数，其值范围应该为：[0,_msize]
        _curr(int):记录了在当前线性表操作过程中，所指向的元素的下标位置，其值范围应该为：[0,_numInList]
    """
    def __init__(self, size=10):
        """
        初始化线性表，默认的线性表的大小为10，也可以由用户通过参数size进行指定
        Args:
            size(int): 指定该线性表的存储数据的容器容量大小，因为采用的是数组形式，故这个大小在整个使用期间是维持不变的
        Returns：返回一个可以直接使用的线性表数据结构类型的实例

        """
        # 所有数据成员的命名都请大家在名字前加下划线（_）
        # python的类型的定义里对私有数据这类访问型能力没有支持，故通过这种下划线起始的方式方便解释器做一些特殊的动作检查

        self._msize = size
        self._numInList = 0
        self._curr = 0

        # 创建一个大小为size的‘数组’（其实在python语言中就是线性表），数组中的元素内容为空值
        # 我们要掌握数组形式下的线性表的实现原理，所以放弃python自带的线性表list
        # 创建一个自定义的线性表List，以后就不会因为语言能力所限而不知所措

        self._listArray = [None]*size

    def clear(self):
        """
        清空当前线性表，使其状态成为空表。
        存储数据的容器可以不用清理，主要设置当前线性表中实际的元素个数为零
        Returns: None
        """
        self._curr, self._numInList = 0, 0

    def insert(self, item):
        """
        在线性表中插入元素item
        元素item的插入位置是由_curr的值所指定，如果_curr的值不在合理的插入位置范围，则抛出Exception
        如果当前线性表中的容量已满，无法插入新的元素，则抛出Exception
        Args:
            item: 要插入到线性表中的元素

        Returns: None
        Raises：
            Exception("List is full"):线性表已经没有空闲空间
            Exception("Bad value for curr"): _curr的值不在其合理的范围中：【0，_numInList]
        """
        if self._numInList == self._msize:
            raise Exception("List is full") # 借助于python的异常机制，当检测到条件不满足时抛出例外，终止程序的继续执行
        if self._curr not in range(0, self._numInList + 1):
            raise Exception("Bad value for curr")
        for i in range(self._numInList, self._curr, -1):
            self._listArray[i] = self._listArray[i-1]
        self._listArray[self._curr] = item
        self._numInList += 1

    # 请同学们根据线上视频的学习，以上面代码为样本补充实现List中定义的其他所有抽象方法
    # 这是一个非常好的实践过程，能够强化理解抽象数据类型和数据结构之间的关系，也能强化逻辑的严谨性


    def append(self, item):
        """
        在线性表的表尾插入元素item
        元素的插入位置是固定的，必须是当前线性表的表尾的直接后继
        如果当前线性表中的容量已满，无法插入新的元素，则抛出Exception
        Args:
            item: 要插入到线性表中的元素

        Returns: None
        Raises:
            Exception("List is full"): 线性表已经没有空闲空间

        """
        if self._numInList == self._msize:
            raise Exception("List is full.")
        self._listArray[self._numInList] = item
        self._numInList += 1

    def remove(self):
        """
        删除线性表中当前位置的元素，并将这个元素做为函数的返回值
        如果线性表是空表，则表明无元素可删除，抛出Exception
        如果指示元素的位置超出了线性表中合理的元素所对应的位置范围，则抛出Exception

        Args:
        Returns:
            T: 线性表中所存储的元素类型为T，返回的是删除的元素（其类型为T）
        Raises:
            Exception("Can't delete from empty list"): 线性表是空表
            Exception("No current element"): 指示待删除的元素的位置不存在，合理的取值范围应该是：[0,_numInList)

        """

        if self.isEmpty():
            raise Exception("Can't delete from empty list.")
        if not self.isInList():
            raise Exception("No current element.")
        it = self._listArray[self._curr]
        for i in range(self._curr, self._numInList-1):
            self._listArray[i] = self._listArray[i+1]
        self._numInList -= 1
        return it

    def setFirst(self):
        """
        将指示元素位置的值设置为表头元素所对应的位置
        规定线性表中的表头元素的位置从0开始计数，这个恰好与Python语言数组中的首元素的位置为0相匹配
        Args:
        Returns:

        """
        self._curr = 0

    def next(self):

        """
        将指示元素位置的值向后移动一位
        Args:
        Returns:

        """
        self._curr += 1

    def prev(self):

        """
        将指示元素位置的值向前移动一位
        Args:
        Returns:

        """
        self._curr -= 1

    def length(self):

        """
        获取线性表中的实际元素个数
        Args:
        Returns:

        """
        return self._numInList

    def setPos(self, pos):

        """
        将指示元素位置的值设置为参数pos指定的值
        Args:
            pos(int): 用户指定的参数值的合理范围应该是[0, _numInList]，但是在代码中没有做检查，意味着无所谓用户指定什么值，
                      但是在真正使用这个值去对线性表进行操作时将会进行合理性检查
        Returns:

        """
        self._curr = pos

    def setValue(self, item):

        """
        将参数item的值用来替换线性表中当前位置所对应的元素
        如果指示当前元素位置的值不在合理范围，则抛出Exception
        Args:
            item: 需要设置当前位置的新元素
        Returns:
        Raises:
            Exception("No current element"): 如果指示元素当前位置的值不在以下范围[0, _numInList)，则抛出该例外

        """
        if not self.isInList():
            raise Exception("No current element.")
        self._listArray[self._curr] = item

    def currValue(self):

        """
        获取当前位置对应在线性表中的元素值
        如果当前位置不在合理范围之内，则抛出Exception
        Args:
        Returns:
            T: 当前位置对应在线性表中的元素值，其类型是T
        Raises:
            Exception("No current element"): 如果指示元素当前位置的值不在以下范围[0, _numInList)，则抛出该例外
        """
        if not self.isInList():
            raise Exception("No current element.")
        return self._listArray[self._curr]

    def isEmpty(self):

        """
        给出线性表是否为空表的结论
        Args:
        Returns:
            bool: 如果线性表是空表，返回True，否则返回False

        """
        return self._numInList == 0

    def isInList(self):

        """
        给出指示元素位置的值是否正确的结论
        Args:
        Returns:
            bool: 如果指示元素位置的值在[0, _numInList)，那么就代表该值是合理的，返回True，否则返回False

        """
        return self._curr >= 0 and self._curr < self._numInList

    def print(self):
        """
        按照规定的格式输出线性表中的数据
        如果是空表，则输出字符串:"The list is empty."
        如果不是空表，则将线性表中的所有数据按照位置序号递增的顺序进行输出，元素之间用空格分割，表头元素左侧用'['引导，表尾元素右侧用']'结束
        Args:
        Returns:

        """
        if self.isEmpty():
            print("The list is empty.")
        else:
            print("[", end="  ")
            for i in range(0, self._numInList):
                print(self._listArray[i], end="  ")
            print("]")

def main():
    list1 = AList()
    list1.insert(1)
    list1.insert(5)
    list1.print()
    list1.remove()
    list1.print()

if __name__ == "__main__":
    main()